package br.com.jr.arq.jsf;

import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.List;

import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.inject.Inject;

import org.springframework.context.ApplicationContext;

import br.com.jr.arq.dao.GenericDao;
import br.com.jr.arq.dao.Persistente;

public class AbstractCrudMBean<T extends Persistente> extends AbstractMBean {

	@Inject
	protected GenericDao dao;
	
	@Inject
	private ApplicationContext application;

	public T obj;
	public List<T> lista;
	public DataModel<T> colecao;
	
	public AbstractCrudMBean() {
		instanciar();
	}
	
	protected void instanciar() {
		ParameterizedType superClass = (ParameterizedType) this.getClass().getGenericSuperclass();
		@SuppressWarnings("unchecked")
		Class<T> classType = (Class<T>) superClass.getActualTypeArguments()[0];
		
		try {
			obj = classType.newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		}		
	}
	
	public String preCadastrar() {
		instanciar();
		setConfirmButton("Cadastrar");
		return getFormPage();
	}
	
	public String cancelar(){
		return "/template/menu_admin";
	}
	
	public String getFormPage(){
		return "/views/admin/" + obj.getClass().getSimpleName().toLowerCase() + "/formulario";
	}

	public String getBuscaPage(){
		return "/views/admin/" + obj.getClass().getSimpleName().toLowerCase() + "/busca";
	}
	
	public String getDirBase(){
		return "/views/admin/" + obj.getClass().getSimpleName().toLowerCase();
	}
	
	public String getListPage(){
		return "/views/admin/" + obj.getClass().getSimpleName().toLowerCase() + "/listagem";
	}
	
	public String preAlterar() {
		obj = colecao.getRowData();
		setConfirmButton("Alterar");
		return "/views/admin/" + obj.getClass().getSimpleName().toLowerCase() + "/formulario";
	}
	
	public String entrarListagem() throws Exception {
		colecao = new ListDataModel<T>((List<T>) getAll());
		return "/views/admin/" + obj.getClass().getSimpleName().toLowerCase() + "/listagem";
	}
	
	protected void beforeCadastrar(){
		
	}
	
	public String cadastrar() throws Exception{
		try {
			beforeCadastrar();
			Collection<String> lista = obj.validar();
			if( lista != null && !lista.isEmpty() ) {
				addMessages(lista);
				return null;
			}
			dao.create( obj );
			addInfo("Cadastro Efetuado com Sucesso");
		} catch (Exception e) {
			e.printStackTrace();
		}
		instanciar();
		return entrarListagem();	
	}
	
	public String atualizar() throws Exception{
		dao.update( obj );
		return entrarListagem();
	}

	public String remover() throws Exception{
		obj = colecao.getRowData();
		dao.remove( obj );
		return entrarListagem();
	}

	@SuppressWarnings("unchecked")
	public Collection<T> buscar(String campo, String valor) throws Exception{
		return (Collection<T>) dao.findByLike(obj.getClass(), campo, valor);  
	}
	
	@SuppressWarnings("unchecked")
	public Collection<T> getAll() throws Exception {
		return (Collection<T>) dao.findAll(obj.getClass());
	}
	
	public T getEntidade() {
		return obj;
	}

	public void setEntidade(T obj) {
		this.obj = obj;
	}

	public List<T> getLista() {
		return lista;
	}

	public void setEntidades(List<T> lista) {
		this.lista = lista;
	}

	public DataModel<T> getModel() {
		return colecao;
	}

	public void setModel(DataModel<T> colecao) {
		this.colecao = colecao;
	}

	public T getObj() {
		return obj;
	}

	public void setObj(T obj) {
		this.obj = obj;
	}

	public DataModel<T> getColecao() {
		return colecao;
	}

	public void setColecao(DataModel<T> colecao) {
		this.colecao = colecao;
	}

	public void setLista(List<T> lista) {
		this.lista = lista;
	}

	public GenericDao getDao() {
		return dao;
	}

	public void setDao(GenericDao dao) {
		this.dao = dao;
	}
	
	@SuppressWarnings("unchecked")
	public T getMBean(String mBean) {
		return (T) application.getBean(mBean);  
	}
	
}